package com.slofzx.nuoda.evaluation.project.builder;

import com.slofzx.nuoda.common.util.DataConvertUtil;
import com.slofzx.nuoda.evaluation.project.compont.CopyExcelComponent;
import com.slofzx.nuoda.evaluation.project.util.BusiUtil;
import com.slofzx.nuoda.evaluation.project.vo.BatchCommonDataVO;
import com.slofzx.nuoda.evaluation.project.vo.ProjectInfoVO;
import com.slofzx.nuoda.evaluation.project.vo.ProjectReportDetailYearVO;
import com.slofzx.nuoda.evaluation.project.vo.ProjectYearDataVO;
import com.slofzx.nuoda.evaluation.steretype.ExcelExportItem;
import com.slofzx.nuoda.excel.entity.CellConfig;
import com.slofzx.nuoda.excel.entity.SheetConfig;
import com.slofzx.nuoda.excel.entity.TemplateConfig;
import com.slofzx.nuoda.expression.ExpressionInvoker;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class BatchExportExcelBuilder extends AbstractVerticalExcelBuilder {
    private List<Map<String,Object>> projectInfoList;
    private Map<String,Map<String,Object>> projectInfoVONameMap;
    private Map<String,Map<String,Object>> projectInfoVOIdMap;
    private Map<String, List<ProjectReportDetailYearVO>> projectReportDetailYearVOMap ;
    private Map<Integer,BatchCommonDataVO> batchCommonDataMap = new HashMap<>();
    private Map<String,Map<Integer,ProjectYearDataVO>> projectYearDataMap;
    protected Map<String, List<ExcelExportItem>> excelExportItemGroupMap;

    public BatchExportExcelBuilder(TemplateConfig config, Map<String, List<ExcelExportItem>> excelExportItemGroupMap, CopyExcelComponent copyExcelComponent) {
        super(config,copyExcelComponent);
        // this.excelExportItemList = excelExportItemList;
//        for (ExcelExportItem item : excelExportItemList) {
//            List<ExcelExportItem> subList = excelExportItemGroupMap.get(item.getGroup());
//            if (subList == null) {
//                subList = new ArrayList<>();
//                excelExportItemGroupMap.put(item.getGroup(), subList);
//            }
//            subList.add(item);
//        }
        this.excelExportItemGroupMap = excelExportItemGroupMap;
    }
    public BatchExportExcelBuilder batchCommonDataVOMap(List<BatchCommonDataVO> batchCommonDataList) {
        final Map<Integer, BatchCommonDataVO> map = batchCommonDataList.stream().filter(f -> Objects.nonNull(f.getYear())).collect(Collectors.toMap(BatchCommonDataVO::getYear, Function.identity(), (v1, v2) -> v1));
        this.batchCommonDataMap = map;
        return this;
    }



//    public BatchExportExcelBuilder(TemplateConfig config) {
//        super(config);
//    }

    public BatchExportExcelBuilder projectMapList(List<Map<String,Object>> projectInfoList) {
        Map<String, Map<String, Object>> projectInfoVONameMap = new HashMap<>();
        Map<String, Map<String, Object>> projectInfoVOIdMap = new HashMap<>();
        for (Map<String, Object> map : projectInfoList) {
            projectInfoVONameMap.put((String) map.get("project_name"), map);
            projectInfoVOIdMap.put((String) map.get("id"), map);
        }
        this.projectInfoVONameMap = projectInfoVONameMap;
        this.projectInfoVOIdMap = projectInfoVOIdMap;
         this.projectInfoList = projectInfoList;
        return this;
    }

    public BatchExportExcelBuilder projectReportDetailYearVOMap(Map<String, List<ProjectReportDetailYearVO>> projectReportDetailYearVOMap) {
        Map<String, List<ProjectReportDetailYearVO>> projectReportDetailYearVONameMap = new HashMap<>();
        for (String key : projectReportDetailYearVOMap.keySet()) {
            final Map<String, Object> map = projectInfoVOIdMap.get(key);
            if (MapUtils.isEmpty(map)) {
                continue;
            }
             List<ProjectReportDetailYearVO> projectYearDataVOS = projectReportDetailYearVOMap.get(key);
            projectYearDataVOS =  projectYearDataVOS.stream().filter(f->f.getYear()>=DataConvertUtil.parse2Int(map.get("project_year"))).collect(Collectors.toList());
            //final Map<Integer, ProjectReportDetailYearVO> yearDataVOMap = projectYearDataVOS.stream().collect(Collectors.toMap(ProjectReportDetailYearVO::getYear, Function.identity(), (v1, v2) -> v1));
            projectReportDetailYearVONameMap.put((String) map.get("project_name"),projectYearDataVOS);
        }
        this.projectReportDetailYearVOMap = projectReportDetailYearVONameMap;
        return this;
    }

    public BatchExportExcelBuilder projectYearDataMap(Map<String,List<ProjectYearDataVO>> projectYearDataMap) {
        Map<String,Map<Integer,ProjectYearDataVO>> projectYearDataMap1 = new HashMap<>();
        for (String key : projectYearDataMap.keySet()) {
            final Map<String, Object> map = projectInfoVOIdMap.get(key);
            if (MapUtils.isEmpty(map)) {
                continue;
            }
            final List<ProjectYearDataVO> projectYearDataVOS = projectYearDataMap.get(key);
            final int projectYear = DataConvertUtil.parse2Int(map.get("project_year"));
            final Map<Integer, ProjectYearDataVO> yearDataVOMap = projectYearDataVOS.stream().peek(p -> p.setYear(p.getYear()+projectYear-1)).collect(Collectors.toMap(ProjectYearDataVO::getYear, Function.identity(), (v1, v2) -> v1));
            projectYearDataMap1.put((String) map.get("project_name"),yearDataVOMap);
        }
        this.projectYearDataMap = projectYearDataMap1;
        return this;
    }


    @Override
    public List<Map<String, Object>> getDataList(SheetConfig sheetConfig) {
        List<Map<String, Object>> dataMapList = new ArrayList<>();

        final List<ProjectReportDetailYearVO> projectReportDetailYearVOS = projectReportDetailYearVOMap.get(sheetConfig.getName());
        if (CollectionUtils.isEmpty(projectReportDetailYearVOS)) {
           // dataMapList.add(new HashMap<>());
            return dataMapList;
        }
        final Map<String, Object> map = projectInfoVONameMap.get(sheetConfig.getName());
        final Integer projectYear = (Integer)map.get("project_year");
        projectReportDetailYearVOS.sort(Comparator.comparing(ProjectReportDetailYearVO::getYear));
        for (ProjectReportDetailYearVO projectReportDetailYearVO : projectReportDetailYearVOS) {
            final Map<String, Object> dataMap = BusiUtil.parseObject2Map(projectReportDetailYearVO,excelExportItemGroupMap);
            Map<Integer, ProjectYearDataVO> yearDataVOMap = projectYearDataMap.get(sheetConfig.getName());
            final Integer year = projectReportDetailYearVO.getYear();
            final ProjectYearDataVO projectYearDataVO = yearDataVOMap.get(year);
            final BatchCommonDataVO batchCommonDataVO = batchCommonDataMap.get(year-projectYear+1);
            dataMap.putAll(BusiUtil.parseObject2Map(projectYearDataVO,excelExportItemGroupMap));
            if (batchCommonDataVO!=null) {
                dataMap.putAll(BusiUtil.parseObject2Map(batchCommonDataVO,excelExportItemGroupMap));
            }
            // 计算公式
            computeExpression(sheetConfig,dataMap);
            dataMapList.add(dataMap);
            //dataMapMap.put(projectReportDetailYearVO.getProjectId(),dataMap);
        }

        return dataMapList;
    }

    @Override
    public Map<String, Object> getSingleDataMap(SheetConfig sheetConfig) {
        return projectInfoVONameMap.get(sheetConfig.getName());

    }

    @Override
    public Map<String, List<Map<String, Object>>> getSheetDataMap() {
        Map<String, List<Map<String, Object>>> result = new HashMap();
        final List<SheetConfig<CellConfig>> sheetConfigList = this.templateConfig.getSheetConfigList();
        final SheetConfig<CellConfig> sheetConfig = sheetConfigList.get(0);
        List<SheetConfig> newSheetConfigList = new ArrayList<>();
        projectInfoList = projectInfoList.stream().
                sorted(Comparator.comparing((s1) -> DataConvertUtil.parse2Double(s1.get("sort")))).collect(Collectors.toList());
        for (Map<String,Object> project : projectInfoList) {
            final String name = (String)project.get("project_name");
            // 复制sheet页配置
            final SheetConfig deepCopy = BusiUtil.deepCopy(sheetConfig, SheetConfig.class);
            deepCopy.setName(name);
            newSheetConfigList.add(deepCopy);
            this.templateConfig.setSheetConfigList(newSheetConfigList);
            // 获取列表数据
            result.put(name, this.getDataList(deepCopy));
        }

        return result;
    }

    /**
     * 行内数据计算公式执行
     * @param sheetConfig
     * @param dataMap
     */
    protected void computeExpression(SheetConfig sheetConfig, Map<String, Object> dataMap) {
        List<CellConfig> cellConfigList = sheetConfig.getCellConfigList();
        for (CellConfig item : cellConfigList) {
            if (!"expression".equals(item.getDataType()) || StringUtils.isBlank(item.getData())) {
                continue;
            }
            try {
                ExpressionInvoker invoker = new ExpressionInvoker(item.getData());
                dataMap.put(item.getData(), invoker.invoke(dataMap));
            } catch (Exception e) {
                logger.error("自定义公式计算失败：{},数据：{}", item.getData(), dataMap, e);
            }
        }
    }

}
